/*
 * @ShutdownHook.java   2008/11/02
 *
 * Copyright 2008 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.LinkedList;

/**
 * Our shutdown hook accessible only from package, as required by the rule of hooking it's extending the Thread class
 * and therefore overridding run method.
 * 
 * @author Leonardo Celati
 */
class ShutdownHook extends Thread implements Constant {
	
	/**
	 * Default constructor b
	 */
	public ShutdownHook() {
    }
	
	/**
	 * As required by the rule of shutdown hook, it's implementing 
	 */
	@Override
    public void run() {
    	// cleanup...but only if we are not already in shutdown mode...
    	//if (!LogFactory.getStatus().equals("SHUTDOWN") )
    		this.shutdown();
    }
    
    /**
     * Free resources...
     */
    @SuppressWarnings("unchecked")
	private synchronized void shutdown() {

    	// different action upon status...
    	switch (LogFactory.getStatus()) {
    	
    		// doing nothing in all case...
	    	default: 
	    		return;
    	
	    	case RUNNING: {
	    		LogPool lp = LogFactory.getLogPool();
		        QueueDumper qd = LogFactory.getQueueDumper();
		        Queue<? extends Entry> q = LogFactory.getQueue();
		        Register<? extends Dumper> r = LogFactory.getRegister();
		        
		        // shutdown QueueDumper
		    	// it is not always running...
		    	if (qd != null) {
		    		try {
		    			qd.kill();
		    		} catch (RuntimeException e) {
		    			
		    			// we know that the qd will launch a RuntimeException 
		    			// if it is not able to stop itself, in this case we look for 
		    			// the group and interrupt, later we will take care of Queue.
			        	ThreadGroup g = Thread.currentThread().getThreadGroup();            	
			        	Thread[] T = new Thread[g.activeCount()];
			        	g.enumerate(T, false);
			        	
			        	qdshutdown:
			        	for (Thread x: Arrays.asList(T)) {
			        		// if it's found...we break the loop
			        		// before we interrupt the thread...
			        		if (x.getName().equals("QueueDumper")) {
			        			x.interrupt();
			        			break qdshutdown;
			        		}
			        	}	    			
		    		}
		        	
		    	}
		    	
		        // before shutdown we try to clear any entry we may have in log    	
		    	try {
					if (q!= null && !q.isEmpty()) {
						LinkedList<? extends Entry> ll = q.unload();
						if (r!=null) {
							r.dispatchToDumper(ll);
							r.kill();
						}
						q.kill();
						//q=null;
					}
				} catch (QueueException e) {
					e.printStackTrace();
				}		
							
				
		    	// now we can close the LogPool...				
				if (lp !=null) {
					lp.kill();
					lp=null;
				}
	    	}
    	}
    }
    
}
